#include "Logger.hpp"
#include "spdlog/spdlog.h"
#include <boost/asio/stream_file.hpp>
#include <boost/filesystem.hpp>
#include <fstream>
#include <iostream>
#include <string>

using namespace boost::filesystem;
using namespace boost;

void async_read_file(asio::stream_file &file, asio::mutable_buffer &buffer,
                     /*asio::basic_streambuf<char> &stream_buf, */ std::size_t &bytes_read,
                     const std::size_t &total_len)
{
    file.async_read_some(buffer, [&](boost::system::error_code ec, std::size_t bytes_transferred) {
        bytes_read += bytes_transferred;
        std::cout << bytes_transferred << std::endl;
        // std::cout << bytes_read << std::endl;
        if (ec)
        {
            std::cout << "read file failed!" << std::endl;
        }
        else
        {
            // stream_buf.commit(bytes_transferred);
            if (bytes_read < total_len)
            {
                async_read_file(file, buffer, /* stream_buf, */ bytes_read, total_len);
            }
            else
            {
                // 已读取完毕
                std::cout << "read file success!" << std::endl;
                ((char*)buffer.data())[total_len] = '\0';
                std::cout << ((char*)buffer.data()) << std::endl;
            }
        }
    });
}

// void async_write2(asio::stream_file &file,
//     asio::mutable_buffer &buffer, std::size_t &bytes_read, 
//     const std::size_t &total_len)
// {
//     asio::streambuf stream_buf;
//     file.async_write_some(
//         buffer, [&](boost::system::error_code ec, std::size_t bytes_transferred) {
//             bytes_read += bytes_transferred;
//             if (ec)
//             {
//                 std::cout << "write file failed!" << std::endl;
//             }
//             else
//             {
//                 // stream_buf.commit(bytes_transferred);
//                 if (bytes_read < total_len)
//                 {
//                    async_write(file, buffer, bytes_read, total_len);
//                 }
//                 else
//                 {
//                     std::cout << "write file success!" << std::endl;
//                     stream_buf.prepare(bytes_read);
//                     std::string str;
//                     std::istream is(&stream_buf);
//                     is >> str;
//                     // std::cout << str << std::endl;
//                     std::cout << buffer.data() << std::endl;
//                 }
//             }
//         }
//     );

// }

int main()
{
    boost::asio::io_context ioc;
    // std::cout << "abc" << std::endl;

    // path path("../statics/shop_data.json");
    path path("../statics/imgs/abcd.png");
    if (!boost::filesystem::exists(path))
    {
        std::cout << "file not exist" << std::endl;
        return 0;
    }

    asio::stream_file file(ioc, path.string(), asio::stream_file::read_only);
    asio::io_service::work work(ioc); // 不让io_context退出

    char data[1024];
    // asio::basic_streambuf<char> stream_buf;
    // asio::streambuf stream_buf;
    asio::mutable_buffer buffer(data, 1024);
    // buffer = stream_buf.prepare(1024);
    std::size_t bytes_read = 0;
    if (!file.is_open())
    {
        std::cout << "file open failed!" << std::endl;
    }
    else
    {
        std::cout << "file open success!" << std::endl;
        std::cout << "file size: " << file.size() << std::endl;
        async_read_file(file, buffer, /*stream_buf, */ bytes_read, file.size());
        // std::istream is(&stream_buf);
        // std::istream is(buffer);
        // std::string str;
        // while (1)
        // {
        //     if (!is.eof())
        //         is >> str;
        //     else
        //         break;
        // }
    }

    // char *data2;
    // data2 = "Hello World!";
    // asio::mutable_buffer buffer2(data, 1024);
    // // asio::const_buffer buffer2(data2, strlen(data2));
    // std::size_t bytes_read2 = 0;
    // asio::stream_file file2(ioc, "../static/abc.txt", asio::stream_file::write_only);
    // async_write2(file2, buffer2, bytes_read2, strlen(data2));

    ioc.run();
}